#include <iostream>
#include <dlfcn.h>
#include "myAes.h"
#define SO_FILE "./libmyAes.so"

// 定义函数指针类型
typedef MyAes* (*CreateFunc)();
typedef void (*DestroyFunc)(MyAes*);
typedef std::string (*openssl_aes_encrypt)(MyAes*,const std::string& password, const std::string& plaintext);// 加密
typedef std::string (*openssl_aes_decrypt)(MyAes*,const std::string& password, const std::string& ciphertext_b64);// 解密
typedef void (*openssl_aes_encrypt_file)(MyAes*,const std::string& input_path, const std::string& output_path,const std::string& password);// 加密
typedef void (*openssl_aes_decrypt_file)(MyAes*,const std::string& input_path, const std::string& output_path,const std::string& password);// 解密

int main() {
    void* handle = dlopen(SO_FILE, RTLD_LAZY);  //
    if (!handle) {
        std::cerr << "Error: " << dlerror() << std::endl;
        return -1;
    }

    // 使用extern "C"声明的函数，dlsym直接引用该函数名称
    CreateFunc create = (CreateFunc)dlsym(handle, "createMyClass");
    DestroyFunc destroy = (DestroyFunc)dlsym(handle, "destroyMyClass");
    //类中的成员函数，dlsym不能直接引用该函数名称,编译出动态库文件后，需要通过命令nm -D libmyAes.so | grep openssl_aes_encrypt_file
    openssl_aes_encrypt aes_encrypt = (openssl_aes_encrypt)dlsym(handle, "_ZN5MyAes19openssl_aes_encryptERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_");
    openssl_aes_decrypt aes_decrypt = (openssl_aes_decrypt)dlsym(handle, "_ZN5MyAes19openssl_aes_decryptERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_");

    openssl_aes_encrypt_file aes_encrypt_file = (openssl_aes_encrypt_file)dlsym(handle, "_ZN5MyAes24openssl_aes_encrypt_fileERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_S7_");
    openssl_aes_decrypt_file aes_decrypt_file = (openssl_aes_decrypt_file)dlsym(handle, "_ZN5MyAes24openssl_aes_decrypt_fileERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_S7_");

    // 错误检查
    const char* dlsym_error = dlerror();
    if (dlsym_error || !create || !destroy || !aes_encrypt|| !aes_decrypt) {
        std::cerr << "Failed to load symbols: " << (dlsym_error ? dlsym_error : "Unknown error") << std::endl;
        dlclose(handle);
        return -1;
    }

    // 使用动态库功能
    MyAes* obj = create();//动态创建类

    //1. 测试文本加密解密闭环
    std::string password = "私人秘钥";
    std::string plaintext = "这是测试内容124dafsd";
    std::cout << "秘钥:"<< password << " 原始文本:"<< plaintext << std::endl;
    // 加密
    std::string encrypted = aes_encrypt(obj,password,plaintext );
    std::cout << "加密结果:" << encrypted << std::endl;
    // 解密
    std::string decrypted = aes_decrypt(obj,password, encrypted);
    std::cout << "解密结果:" << decrypted << std::endl;

    //2. 测试文件加密解密闭环
    std::string src_path = "./src.txt";
    std::string encrypt_path = "./encrypt_file.txt";
    std::string decrypt_path = "./decrypt_file.txt";

    aes_encrypt_file(obj,src_path,encrypt_path,password);
    aes_decrypt_file(obj,encrypt_path,decrypt_path,password);

    destroy(obj);//销毁类
    dlclose(handle);  // 卸载库‌
    return 0;
}
